<?php
/**
 * jishupu-cms
 * @Author:技术铺<jishupu@qq.com>
 * @Date: 2022/3/16
 */

namespace App\Services;

/**
 * 分类树
 *
 * Class TreeService
 * @package App\Services
 */
class TreeService
{
    /**
     * 生成分类树
     * @param array $data 扁平化数据
     * @param string $primary_id 默认id
     * @param string $pid 默认父id：parent_id
     * @param string $children 子集 默认children
     * @return array
     */
    public static function make($data = [], $primary_id = "id", $pid = "parent_id", $children = "children")
    {
        if (empty($data)) return [];
        $resetData = [];
        collect($data)->each(function ($item) use ($primary_id, &$resetData) {
            $resetData[$item[$primary_id]] = is_object($item) ? json_decode(json_encode($item), true) : $item;
        });
        $tree = [];
        collect($resetData)->each(function ($item, $key) use ($primary_id, $pid, $children, &$resetData, &$tree) {
            if (isset($item[$pid]) && $item[$pid] > 0) {
                $resetData[$item[$pid]][$children][] = &$resetData[$key];
            } else {
                $tree[] = &$resetData[$key];
            }
        });
        return $tree;
    }

    /**
     * 根据指定父级ID获取所有子类ID集
     * @param array $data 扁平化数据
     * @param int $parent_id
     * @param string $primary_id
     * @param string $pid
     * @return array|int[]
     */
    public static function getSubIdsByParentId($data = [], $parent_id = 0, $primary_id = "id", $pidField = "parent_id")
    {
        if (empty($data) || !$parent_id) return [];
        $subIds = [];
        collect($data)->each(function ($item) use ($data, $parent_id, $primary_id, $pidField, &$subIds) {
            if ($item[$pidField] == $parent_id) {
                array_push($subIds, $item[$primary_id]);
                $subIds = array_merge($subIds, self::getSubIdsByParentId($data, $item[$primary_id]));
            }
        });
        return $subIds;
    }


    /**
     * 根据父类ID获取子类分类树
     * @param array $data
     * @param int $parent_id
     * @param string $primary_id
     * @param string $pidField
     * @param string $children
     * @return array
     */
    static function getSubsTreeByParentId($data = [], $parent_id = 0, $primary_id = "id", $pidField = "parent_id", $children = "children")
    {
        if (empty($data) || !$parent_id) return [];
        $tree = [];
        collect($data)->each(function ($item) use ($data, $parent_id, $primary_id, $pidField, &$tree, $children) {
            if ($item[$pidField] == $parent_id) {
                $getSub = self::getSubsTreeByParentId($data, $item[$primary_id]);
                if (!empty($getSub)) {
                    $item[$children] = $getSub;
                }
                array_push($tree, $item);
            }
        });
        return $tree;
    }

    /**
     * 根据指定父级ID获取所有子类数据
     * @param array $data // 扁平化数据
     * @param int $parent_id
     * @param string $primary_id
     * @param string $pidField
     * @return array
     */
    public static function getAllSubsByParentId($data = [], $parent_id = 0, $primary_id = "id", $pidField = "parent_id")
    {
        if (empty($data) || !$parent_id) return [];
        $subs = [];
        collect($data)->each(function ($item) use ($data, $parent_id, $primary_id, $pidField, &$subs) {
            if ($item[$pidField] == $parent_id) {
                array_push($subs, $item);
                $subs = array_merge($subs, self::getAllSubsByParentId($data, $item[$primary_id]));
            }
        });
        return $subs;
    }

    /**
     * 根据指定ID获取所有父级ID集
     * @param array $data 扁平化数据
     * @param int $id
     * @param string $primary_id
     * @param string $pidField
     * @return array
     */
    static function getParentIdsById($data = [], $id = 0, $primary_id = "id", $pidField = "parent_id")
    {
        if (empty($data) || !$id) return [];
        $collectionKeyBy = collect($data)->keyBy($primary_id)->all();
        $pid = !empty($collectionKeyBy && isset($collectionKeyBy[$id])) ? $collectionKeyBy[$id]['parent_id'] : 0;
        $parentIds = [];
        if (!empty($collectionKeyBy)) {
            while ($pid > 0) {
                foreach ($collectionKeyBy as $id => $value) {
                    if ($pid == $id) {
                        array_unshift($parentIds, $id);
                        $pid = $value[$pidField];
                        if ($pid == 0) {
                            break;
                        }
                    }
                }
            }
        }
        return $parentIds;
    }

    /**
     * 根据指定ID获取所有父级数据
     * @param array $data 扁平化数据
     * @param int $id
     * @param string $primary_id
     * @param string $pidField
     * @return array
     */
    static function getAllParentsById($data = [], $id = 0, $primary_id = "id", $pidField = "parent_id")
    {
        if (empty($data) || !$id) return [];
        $collectionKeyBy = collect($data)->keyBy($primary_id)->all();
        $pid = !empty($collectionKeyBy && isset($collectionKeyBy[$id])) ? $collectionKeyBy[$id]['parent_id'] : 0;
        $parents = [];
        if (!empty($collectionKeyBy)) {
            while ($pid > 0) {
                foreach ($collectionKeyBy as $id => $value) {
                    if ($pid == $id) {
                        array_unshift($parents, $value);
                        $pid = $value[$pidField];
                        if ($pid == 0) {
                            break;
                        }
                    }
                }
            }
        }
        return $parents;
    }

}
